import React, { useState, useRef, useEffect } from 'react'
import { Input, Button, Space, Typography, Spin, Tooltip, Badge, Card, List, message } from 'antd'
import { SendOutlined, ClearOutlined, FolderOpenOutlined } from '@ant-design/icons'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import axios from 'axios'

const { Text } = Typography

interface Message {
  role: 'user' | 'assistant' | 'system'
  content: string
}

interface FileContext {
  name: string
  content: string
  path?: string
  displayPath?: string
  summary: string
  lastAccessed: string
}

interface BrowseResponse {
  files: {
    name: string
    path: string
    displayPath: string
    content: string
  }[]
  currentPath: string
  isProjectRoot: boolean
  totalFiles: number
}

interface FileInfo {
  name: string
  path: string
  full_path: string
  is_loaded: boolean
}

interface Config {
  model_name: string
  ollama_url: string
  persist_dir: string
  loaded_paths: string[]
  status: {
    is_initialized: boolean
    last_load_time: string | null
    loaded_paths: string[]
    file_metadata: Record<string, any>
  }
}

const API_URL = import.meta.env.VITE_API_URL || 'http://127.0.0.1:5000'

function ChatInterface() {
  const [messages, setMessages] = useState<Message[]>([])
  const [input, setInput] = useState('')
  const [isLoading, setIsLoading] = useState(false)
  const [modelName, setModelName] = useState('llama3.2:latest')
  const [contextFiles, setContextFiles] = useState<FileContext[]>(() => {
    try {
      const savedFiles = localStorage.getItem('contextFiles')
      return savedFiles ? JSON.parse(savedFiles) : []
    } catch (error) {
      console.error('Error loading saved files:', error)
      return []
    }
  })
  const [selectedFolder, setSelectedFolder] = useState<string>(() => {
    return localStorage.getItem('selectedFolder') || ''
  })
  const fileInputRef = useRef<HTMLInputElement>(null)
  const [error, setError] = useState<string | null>(null)
  const [config, setConfig] = useState<Config | null>(null)
  const [files, setFiles] = useState<FileInfo[]>([])
  const [currentDirectory, setCurrentDirectory] = useState<string>('.')
  const messagesEndRef = useRef<HTMLDivElement>(null)

  // 加载模型配置
  useEffect(() => {
    const loadConfig = async () => {
      try {
        console.log('正在连接后端服务器...', API_URL)
        const response = await axios.get(`${API_URL}/api/config`, {
          timeout: 5000, // 5秒超时
          validateStatus: function (status) {
            return status >= 200 && status < 500 // 允许任何非500错误的状态码
          }
        })
        console.log('成功连接到后端服务器')
        setModelName(response.data.model)
        setConfig(response.data)
        setError(null)
      } catch (error: any) {
        console.error('加载模型配置失败:', error)
        let errorMessage = '无法连接到后端服务器，请检查：'
        if (error.code === 'ECONNREFUSED') {
          errorMessage += '\n1. 后端服务是否已启动（python src/backend/llama_model.py）'
          errorMessage += '\n2. 服务地址是否正确（当前：' + API_URL + '）'
          errorMessage += '\n3. 端口5000是否被占用'
        } else if (error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') {
          errorMessage += '\n1. 后端服务响应超时'
          errorMessage += '\n2. 检查后端服务是否正常运行'
        } else if (error.response) {
          errorMessage += '\n服务器返回错误：' + (error.response.data?.error || error.message)
        } else if (error.request) {
          errorMessage += '\n1. 网络连接是否正常'
          errorMessage += '\n2. 后端地址是否正确（当前：' + API_URL + '）'
          errorMessage += '\n3. 是否有跨域限制'
        } else {
          errorMessage += '\n' + (error.message || '未知错误')
        }
        setError(errorMessage)
      }
    }
    loadConfig()
  }, [])

  // 保存文件到 localStorage
  useEffect(() => {
    try {
      localStorage.setItem('contextFiles', JSON.stringify(contextFiles))
    } catch (error) {
      console.error('Error saving files to localStorage:', error)
    }
  }, [contextFiles])

  // 保存选中的文件夹路径
  useEffect(() => {
    localStorage.setItem('selectedFolder', selectedFolder)
  }, [selectedFolder])

  // 加载文件列表
  useEffect(() => {
    const loadFiles = async () => {
      try {
        const response = await axios.get(`${API_URL}/api/browse`, {
          params: { directory: currentDirectory }
        })
        if (response.data.success) {
          setFiles(response.data.files)
          setError(null)
        } else {
          setError(response.data.message)
        }
      } catch (err) {
        setError('加载文件列表失败')
        console.error('Error loading files:', err)
      }
    }
    loadFiles()
  }, [currentDirectory])

  // 自动滚动到最新消息
  useEffect(() => {
    messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
  }, [messages])

  const handleClearFiles = () => {
    setContextFiles([])
    setSelectedFolder('')
    message.info('所有已加载的文件已被清除')
  }

  const handleFolderSelect = async (e: React.FormEvent) => {
    e.preventDefault()
    
    console.log('\n=== 开始加载文件夹 ===')
    console.log(`请求路径: ${selectedFolder}`)
    console.time('文件夹加载耗时')

    if (!selectedFolder.trim()) {
      console.log('错误: 空路径')
      message.warning('请输入要加载的文件夹路径')
      return
    }

    try {
      setIsLoading(true)
      console.log('发送请求到服务器...')
      const response = await axios.post<BrowseResponse & { hasMore?: boolean, message?: string }>(`${API_URL}/api/browse`, {
        path: selectedFolder,
        maxFiles: 500
      })
      
      console.log('服务器响应:', {
        totalFiles: response.data.totalFiles,
        hasMore: response.data.hasMore,
        message: response.data.message
      })
      
      const { files, totalFiles, hasMore, message: responseMessage } = response.data
      
      if (files && Array.isArray(files)) {
        console.log(`\n=== 文件过滤 ===`)
        console.log(`原始文件数量: ${files.length}`)
        
        // 限制每个文件的大小，跳过过大的文件
        const MAX_FILE_SIZE = 100 * 1024 // 100KB
        const filteredFiles = files.filter(file => {
          const size = (file.content.length / 1024).toFixed(1)
          if (file.content.length > MAX_FILE_SIZE) {
            console.log(`跳过大文件: ${file.name} (${size}KB)`)
            return false
          }
          console.log(`处理文件: ${file.name} (${size}KB)`)
          return true
        })
        
        console.log(`过滤后文件数量: ${filteredFiles.length}`)

        // 首先加载文件，不生成摘要
        console.log('\n=== 初始化文件上下文 ===')
        const newContextFiles: FileContext[] = filteredFiles.map(file => ({
          name: file.name,
          content: file.content,
          path: file.displayPath,
          summary: '加载中...', // 默认摘要
          lastAccessed: new Date().toISOString()
        }))

        // 先保存文件，让用户可以使用
        console.log('保存文件到状态和 localStorage...')
        setContextFiles(newContextFiles)
        localStorage.setItem('contextFiles', JSON.stringify(newContextFiles))

        message.success(`已加载 ${newContextFiles.length} 个文件，正在生成摘要...`)

        // 异步生成摘要
        const generateSummaries = async () => {
          console.log('\n=== 开始生成文件摘要 ===')
          console.time('摘要生成总耗时')
          
          const batchSize = 3 // 每批处理的文件数
          const updatedFiles = [...newContextFiles]
          
          for (let i = 0; i < updatedFiles.length; i += batchSize) {
            const batch = updatedFiles.slice(i, i + batchSize)
            console.log(`\n处理批次 ${Math.floor(i/batchSize) + 1}/${Math.ceil(updatedFiles.length/batchSize)}:`)
            
            await Promise.all(batch.map(async (file) => {
              console.time(`摘要生成 - ${file.name}`)
              try {
                const summaryResponse = await axios.post('/api/chat', {
                  model: modelName,
                  messages: [{
                    role: 'system',
                    content: '请用一句话总结这个文件的主要功能和用途。保持简洁。'
                  }, {
                    role: 'user',
                    content: `文件名：${file.name}\n内容：${file.content}`
                  }],
                  stream: false
                })
                file.summary = summaryResponse.data.response || '无摘要'
                console.log(`✓ ${file.name}: ${file.summary}`)
              } catch (error) {
                console.warn(`✗ ${file.name}: 生成失败`, error)
                file.summary = '无摘要'
              }
              console.timeEnd(`摘要生成 - ${file.name}`)
            }))

            // 更新进度
            setContextFiles([...updatedFiles])
            localStorage.setItem('contextFiles', JSON.stringify(updatedFiles))
            
            const progress = Math.min(100, Math.round(((i + batchSize) / updatedFiles.length) * 100))
            console.log(`进度: ${progress}%`)
          }

          console.timeEnd('摘要生成总耗时')
          console.log('=== 摘要生成完成 ===\n')
        }

        // 在后台生成摘要
        generateSummaries().catch(error => {
          console.error('生成摘要时出错:', error)
          message.warning('部分文件可能没有摘要')
        })
      }
    } catch (error: any) {
      console.error('加载文件夹失败:', error)
      console.error('错误详情:', {
        name: error.name,
        message: error.message,
        response: error.response?.data
      })
      
      const errorDetails = error.response?.data?.details || {}
      let errorMessage = '无法读取文件夹内容'
      
      if (errorDetails.limit) {
        errorMessage = `文件数量超过限制（最大 ${errorDetails.limit} 个文件）`
      } else {
        errorMessage = error.response?.data?.error || error.message
      }
      
      message.error(`${errorMessage}\n请求路径: ${errorDetails.requestedPath || selectedFolder}`)
    } finally {
      setIsLoading(false)
      console.timeEnd('文件夹加载耗时')
    }
  }

  const handleSend = async () => {
    if (!input.trim()) return

    console.log('\n=== 开始问答会话 ===')
    console.time('问答总耗时')
    
    const userMessage: Message = {
      role: 'user',
      content: input,
    }

    setMessages((prev) => [...prev, userMessage])
    setInput('')
    setIsLoading(true)
    setError(null)

    try {
      console.log(`问题: ${input}`)
      console.log(`已加载文件数量: ${contextFiles.length}`)
      
      // 计算所有文件的总大小
      const totalSize = contextFiles.reduce((sum, file) => sum + file.content.length, 0)
      console.log(`总文件大小: ${(totalSize / 1024).toFixed(2)}KB`)

      console.log('\n=== 文件相关性分析 ===')
      console.time('相关性计算')
      // 根据问题计算文件相关性并排序
      const rankedFiles = contextFiles
        .map(file => {
          const relevance = calculateRelevance(file, input)
          console.log(`${file.path || file.name}: 得分 ${relevance}`)
          return { ...file, relevance }
        })
        .sort((a, b) => b.relevance - a.relevance)
      console.timeEnd('相关性计算')

      console.log('\n=== 相关性排序结果 ===')
      rankedFiles.forEach((file, index) => {
        console.log(`[${index + 1}] ${file.path || file.name}`)
        console.log(`  - 相关性得分: ${file.relevance}`)
        console.log(`  - 大小: ${(file.content.length / 1024).toFixed(1)}KB`)
        console.log(`  - 摘要: ${file.summary}`)
      })

      console.log('\n=== 构建系统消息 ===')
      console.time('消息构建')
      // 构建增强的系统消息
      const systemMessage: Message = {
        role: 'system',
        content: `你是一个专注于代码分析的AI助手。请基于提供的文件内容回答问题。

=== 文档概览 ===
总文件数: ${contextFiles.length}
总大小: ${(totalSize / 1024).toFixed(2)}KB
查询时间: ${new Date().toLocaleString()}

=== 文件列表 ===
${rankedFiles.map((file, index) => `
[${index + 1}] ${file.path || file.name}
- 大小: ${(file.content.length / 1024).toFixed(1)}KB
- 相关性得分: ${file.relevance}
- 最后访问: ${new Date(file.lastAccessed).toLocaleString()}
- 摘要: ${file.summary}
`).join('\n')}

=== 文件内容 ===
${rankedFiles.map(file => `
<file 
  path="${file.path || file.name}"
  size="${(file.content.length / 1024).toFixed(1)}KB"
  relevance="${file.relevance}"
>
\`\`\`${file.name.split('.').pop() || ''}
${file.content.trim()}
\`\`\`
</file>
`).join('\n')}

回答要求：
1. 必须基于上述文件内容回答问题
2. 引用代码时，指明具体文件和行号
3. 如果文件中没有相关信息，明确说明
4. 不要使用你的基础知识回答与文件无关的问题
5. 回答开始时说明使用了哪些文件作为参考

用户问题：${input}`
      }
      console.timeEnd('消息构建')

      console.log('\n=== 发送到模型的上下文统计 ===')
      console.log(`系统消息大小: ${(systemMessage.content.length / 1024).toFixed(2)}KB`)
      console.log(`最近消息数量: ${Math.min(4, messages.length)}`)

      // 只保留最近的对话记录
      const recentMessages = messages.slice(-4)

      console.log('\n=== 发送请求到AI服务器 ===')
      console.log('请求URL:', `${API_URL}/api/chat`)
      console.log('请求参数:', {
        model: modelName,
        messagesCount: recentMessages.length + 2, // +2 for system and user message
        systemMessageSize: (systemMessage.content.length / 1024).toFixed(2) + 'KB'
      })

      const response = await axios.post(`${API_URL}/api/chat`, {
        model: modelName,
        messages: [
          systemMessage,
          ...recentMessages,
          userMessage
        ],
        stream: true
      }, {
        timeout: 60000, // 60秒超时
        validateStatus: function (status) {
          return status >= 200 && status < 500
        }
      })

      console.log(`\n=== 响应统计 ===`)
      console.log(`响应时间: ${response.data.response?.length || 0}ms`)
      console.log(`响应内容长度: ${response.data.response?.length || 0} 字符`)

      const assistantMessage: Message = {
        role: 'assistant',
        content: response.data.response || response.data.message?.content || '无响应'
      }

      setMessages((prev) => [...prev, assistantMessage])
      
      // 更新文件访问时间
      console.log('\n=== 更新文件访问时间 ===')
      const updatedFiles = contextFiles.map(file => ({
        ...file,
        lastAccessed: new Date().toISOString()
      }))
      setContextFiles(updatedFiles)
      localStorage.setItem('contextFiles', JSON.stringify(updatedFiles))

    } catch (error: any) {
      console.error('\n=== 错误信息 ===')
      console.error('类型:', error.name)
      console.error('消息:', error.message)
      console.error('详情:', error.response?.data || '无详细信息')
      console.error('堆栈:', error.stack)
      
      let errorMessage = '无法连接到AI服务器，请检查：'
      if (error.code === 'ECONNREFUSED') {
        errorMessage += '\n1. 后端服务是否已启动（python src/backend/llama_model.py）'
        errorMessage += '\n2. 服务地址是否正确（当前：' + API_URL + '）'
        errorMessage += '\n3. 端口5000是否被占用'
      } else if (error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') {
        errorMessage += '\n1. 请求超时，服务器响应时间过长'
        errorMessage += '\n2. 检查后端服务是否正常运行'
        errorMessage += '\n3. 考虑增加超时时间'
      } else if (error.response) {
        errorMessage += '\n服务器返回错误：' + (error.response.data?.error || error.message)
      } else {
        errorMessage += '\n' + (error.message || '未知错误')
      }
      
      message.error(errorMessage)
    } finally {
      setIsLoading(false)
      console.timeEnd('问答总耗时')
      console.log('\n=== 会话完成 ===\n')
    }
  }

  // 计算文件与问题的相关性
  function calculateRelevance(file: FileContext, question: string): number {
    const fileName = file.name.toLowerCase()
    const filePath = (file.path || '').toLowerCase()
    const fileContent = file.content.toLowerCase()
    const questionWords = question.toLowerCase().split(/\W+/).filter(Boolean)
    
    let score = 0
    
    // 检查文件名相关性
    questionWords.forEach(word => {
      if (fileName.includes(word)) score += 3
      if (filePath.includes(word)) score += 2
      if (fileContent.includes(word)) score += 1
    })
    
    // 检查文件类型相关性
    const fileExt = fileName.split('.').pop() || ''
    const codeKeywords = ['js', 'ts', 'jsx', 'tsx', 'py', 'java', 'cpp', 'c', 'html', 'css']
    if (codeKeywords.includes(fileExt)) score += 2
    
    return score
  }

  const handleLoadFile = async (filePath: string) => {
    try {
      const response = await axios.post(`${API_URL}/api/load`, { file_path: filePath })
      if (response.data.success) {
        // 重新加载配置以更新状态
        const configResponse = await axios.get(`${API_URL}/api/config`)
        setConfig(configResponse.data)
        setError(null)
      } else {
        setError(response.data.message)
      }
    } catch (err) {
      setError('加载文件失败')
      console.error('Error loading file:', err)
    }
  }

  return (
    <div className="flex h-screen bg-gray-100">
      {/* 左侧文件浏览器 */}
      <div className="w-1/4 p-4 bg-white shadow-lg overflow-y-auto">
        <h2 className="text-xl font-bold mb-4">文件浏览器</h2>
        {error && (
          <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
            {error}
          </div>
        )}
        <div className="mb-4">
          <button
            onClick={() => setCurrentDirectory('.')}
            className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
          >
            返回根目录
          </button>
        </div>
        <div className="space-y-2">
          {files.map((file, index) => (
            <div
              key={index}
              className="flex items-center justify-between p-2 hover:bg-gray-100 rounded"
            >
              <span className="flex-1">{file.path}</span>
              <button
                onClick={() => handleLoadFile(file.full_path)}
                className={`px-3 py-1 rounded ${
                  file.is_loaded
                    ? 'bg-green-500 text-white'
                    : 'bg-blue-500 text-white hover:bg-blue-600'
                }`}
                disabled={file.is_loaded}
              >
                {file.is_loaded ? '已加载' : '加载'}
              </button>
            </div>
          ))}
        </div>
      </div>

      {/* 右侧聊天界面 */}
      <div className="flex-1 flex flex-col">
        {/* 状态栏 */}
        <div className="bg-white shadow-sm p-4">
          <h2 className="text-lg font-semibold">状态信息</h2>
          {config ? (
            <div className="text-sm text-gray-600">
              <p>模型: {config.model_name}</p>
              <p>服务状态: {config.status.is_initialized ? '已初始化' : '未初始化'}</p>
              <p>已加载文件数: {config.status.loaded_paths.length}</p>
            </div>
          ) : (
            <p className="text-sm text-gray-500">加载配置中...</p>
          )}
        </div>

        {/* 消息列表 */}
        <div className="flex-1 overflow-y-auto p-4 space-y-4">
          {messages.map((message, index) => (
            <div
              key={index}
              className={`p-4 rounded-lg max-w-3xl ${
                message.role === 'user'
                  ? 'bg-blue-100 ml-auto'
                  : 'bg-white shadow-md'
              }`}
            >
              <p className="whitespace-pre-wrap">{message.content}</p>
            </div>
          ))}
          <div ref={messagesEndRef} />
        </div>

        {/* 输入框 */}
        <div className="p-4 bg-white shadow-lg">
          {error && (
            <div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mb-4">
              {error}
            </div>
          )}
          <div className="flex space-x-4">
            <input
              type="text"
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyPress={(e) => e.key === 'Enter' && handleSend()}
              placeholder="输入您的问题..."
              className="flex-1 p-2 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
              disabled={isLoading}
            />
            <button
              onClick={handleSend}
              disabled={isLoading}
              className="bg-blue-500 text-white px-6 py-2 rounded hover:bg-blue-600 disabled:bg-gray-400"
            >
              {isLoading ? '发送中...' : '发送'}
            </button>
          </div>
        </div>
      </div>
    </div>
  )
}

export default ChatInterface 